package com.demo.mangyThread.threadException.csdn;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

/**
 * @Author: lkz
 * @Title: ExceptionInCurThread
 * @Description: 可以在当前通过try catch的方式捕获其他线程抛出的异常吗?
 * @Date: 2023/3/28 11:00
 */
@Slf4j
public class ExceptionInChildThread implements Runnable{

    @Override
    public void run() {
        throw new RuntimeException("子线程发生了异常...");
    }

    /**
     * 模拟子线程发生异常
     *
     * @throws InterruptedException
     */
    private static void exceptionThread() throws InterruptedException {
        new Thread(new ExceptionInChildThread()).start();
        TimeUnit.MILLISECONDS.sleep(200L);
        new Thread(new ExceptionInChildThread()).start();
        TimeUnit.MILLISECONDS.sleep(200L);
        new Thread(new ExceptionInChildThread()).start();
        TimeUnit.MILLISECONDS.sleep(200L);
        new Thread(new ExceptionInChildThread()).start();
        TimeUnit.MILLISECONDS.sleep(200L);
    }


    /**
     * 在主线程尝试通过try catch捕获异常
     */
    private static void catchInMain() {
        try {
            exceptionThread();
        } catch (Exception e) {
            //无法捕获发生在其他线程中的异常
            log.error("捕获到了异常?", e);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ExceptionInChildThread.catchInMain();
    }


    /**
     *
     * 预期:
     *      在运行第一个线程的时候发生了异常，被catch捕获，打印捕获到了异常?和异常堆栈且后面的线程将不会运行。
     * 实际运行结果:
     *      并不符合预期。
     *      没有被try catch捕获。
     *      后续的线程没有因为第一个线程发生异常而跳过
     *  结论:
     * 无法在一个线程中通过try catch捕获另外一个线程的异常。
     *  解决方案：
     *      在每个线程内部run()方法内通过try catch捕获当前线程发生的异常。
     *      缺点：每个线程都需要编写重复的try catch 代码
     *      使用线程异常处理器UncaughtExceptionHandler
     *      给所有线程设置统一的异常处理器
     *      给每个线程设置特定的异常处理器
     *      给线程组设置异常处理器
     *      给线程池设置异常处理器
     *      因为线程池也是通过new Thread()的方式创建的线程，所以思想与上面两种方法一致。
     *      注意：execute()与submit()方式对 异常处理的不同
     */

}
